package tech.yixiyun.framework.kuafu.bean;


import tech.yixiyun.framework.kuafu.bean.annotation.Bean;
import tech.yixiyun.framework.kuafu.enhance.hancer.IEnhancer;
import tech.yixiyun.framework.kuafu.log.LOGGER;

/**
 * Bean定义类，每个Bean类都对应一个定义实例
 */
public final class BeanDefinition {


    /**
     * 注册时的Bean类
     */
    private Class originalClass;

    /**
     * 最终使用的Bean类。当这个类使用了
     * 实例化的对象也会是这个代理类的实例。但不用担心，代理类都是继承了原始类的。
     * 如果这个类没使用 @Enhance注解，那这个finalClass 就是 originalClass
     */
    private Class finalClass;
    /**
     * 是否延迟实例化
     */
    private boolean lazyInit;

    /**
     * finalClass的实例
     */
    private volatile Object instance;

    /**
     * 实例化方式，单例还是多例，默认单例
     */
    private BeanMode beanMode = BeanMode.SINGLETON;

    /**
     * 该组件的备注
     */
    private String remark;

    /**
     * 这个类使用的Enhancer
     */
    private Class<? extends IEnhancer>[] enhancerClasses;

    /**
     * Bean实例的状态，单例的Bean，必须state为over的才可对外提供引用
     */
    private volatile BeanState state;

    public BeanDefinition(){}

    public BeanDefinition(Class beanClass) {
        this(beanClass, false);
    }

    /**
     * 如果Bean类没有使用@Bean注解，那么就使用指定的lazyInit值，否则使用@Bean注解的值
     * @param beanClass
     * @param lazyInit
     */
    public BeanDefinition(Class beanClass, boolean lazyInit) {
        this.originalClass = beanClass;
        this.finalClass = beanClass;
        Bean bean = (Bean) beanClass.getAnnotation(Bean.class);
        this.state = BeanState.NOT_INIT;
        if (bean != null) {
            this.lazyInit = bean.lazyInit();
            this.beanMode = bean.mode();
            this.remark = bean.remark();
        } else {
            this.lazyInit = lazyInit;
        }
    }




    public Class getOriginalClass() {
        return originalClass;
    }

    protected void setOriginalClass(Class originalClass) {
        this.originalClass = originalClass;
    }

    public Class getFinalClass() {
        return finalClass;
    }

    public void setFinalClass(Class finalClass) {
        this.finalClass = finalClass;
    }

    public boolean getIsLazyInit() {
        return lazyInit;
    }

    protected void setIsLazyInit(boolean lazyInit) {
        this.lazyInit = lazyInit;
    }

    public Object getInstance() {
        return instance;
    }

    protected void setInstance(Object instance) {
        this.instance = instance;
    }



    /**
     * 获取这个类所有的增强器
     * @return
     */
    public IEnhancer[] getEnhances() {
        if (enhancerClasses == null || enhancerClasses.length == 0) {
            return null;
        }
        IEnhancer[] enhancers = new IEnhancer[enhancerClasses.length];
        for (int i = 0; i < enhancerClasses.length; i++) {
            enhancers[i] = BeanContext.getBean(enhancerClasses[i]);
        }
        return enhancers;
    }


    public Class<? extends IEnhancer>[] getEnhancerClasses() {
        return enhancerClasses;
    }

    public void setEnhancerClasses(Class<? extends IEnhancer>[] enhancerClasses) {
        this.enhancerClasses = enhancerClasses;
    }

    public BeanMode getBeanMode() {
        return beanMode;
    }

    protected void setBeanMode(BeanMode beanMode) {
        this.beanMode = beanMode;
    }

    public String getRemark() {
        return remark;
    }

    protected void setRemark(String remark) {
        this.remark = remark;
    }

    public BeanState getState() {
        return state;
    }

    /**
     * 更新实例的状态，返回是否更新成功
     * 这个方法因为加锁了，所以只会按顺序执行
     * @param state
     * @return
     */
    protected boolean setState(BeanState state) {
        switch (state) {

            case INITING:
                this.state = state;
                return true;

            case COOPERATING:
                //如果这个bean的状态还没更新，就说明还没实例化好，就不能立即返回，
                //否则依赖获取的就是个null了
                if (this.state == BeanState.NOT_INIT) {
                    return false;
                }
                synchronized (this) {
                    if (this.state == BeanState.INITING) {
                        this.state = state;
                    }
                }
                //已过了这个状态的就算了，不用标记为合作态了
                return true;

            case READY:
                this.state = state;
                return true;

            case OVER:
                //如果尝试结束，就检测是否已经ready了
                if (this.state.getValue() < BeanState.READY.getValue()){
                    return false;
                }

                if (this.state == BeanState.OVER || this.state == BeanState.TRY_OVER) {
                    return true;
                }

                synchronized (this) {
                    this.state = BeanState.TRY_OVER;
                    //检查它的依赖是否状态都over，如果是，就over，不是回退状态，继续等待
                    if (BeanContext.checkDependencyIsAllOk(originalClass)) {
                        this.state = BeanState.OVER;
                        return true;
                    }

                    this.state = BeanState.READY;
                    //依赖都没初始化完，就先让出CPU资源，不要不停循环
                    return false;
                }


        }

        return true;
    }


}
